home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / AppsToGo / AppsToGo.docs / =AppWannabe.mult.doc.app < prev    next >
Encoding:
Text File  |  1994-09-22  |  6.7 KB  |  161 lines  |  [TEXT/MPS ]

  1. Multiple documents has now gotten a lot easier, thanks to the OpenDoc utility
  2. PartMaker™.  It is a convenient way to start a new Part Editor for OpenDoc,
  3. but really it is a generic tool, so I've gone ahead and decided to use it for
  4. AppsToGo, as well.  (Why not?  PartMaker was written using AppsToGo...)
  5.  
  6. First off, if you don't want to, you don't have to have a different source file
  7. for a different document.  The functions in the source file Window.c will be
  8. called by default for any document that is created.  In each function, where
  9. appropriate, you could simply test the OSType of the document the function is
  10. called to manage, and then execute the appropriate code based on this OSType.
  11.  
  12. For example, the Window.c function ContentClick would be called by default for
  13. mouse clicks in the content of a window.  You could do something like the below
  14. to determine what document type you are handling when this is called, and then
  15. do the appropriate thing for that document type.
  16.  
  17. void    ContentClick(WindowPtr window, EventRecord *event, Boolean firstClick)
  18. {
  19. #ifndef __MWERKS__
  20. #pragma unused (firstClick)
  21. #endif
  22.  
  23.     ControlHandle    ctl;
  24.     short            action, cnum;
  25.     FileRecHndl        frHndl;
  26.  
  27.     cnum = IsCtlEvent(window, event, &ctl, &action);
  28.         /* That was easy.  Scrolling was just handled.  Other stuff would be handled
  29.         ** by IsCtlEvent, if we had other stuff to do.  We don't have any other
  30.         ** controls in the content besides the document scrollbars. */
  31.  
  32.     frHndl = (FileRecHndl)GetWRefCon(window);
  33.     switch ((*frHndl)->fileState.sfType) {
  34.         case 'doc1':
  35.             /* do "stuff" appropriate for 'doc1' based on the cnum returned. */
  36.             break;
  37.         case 'doc2':
  38.             /* do "stuff" appropriate for 'doc2' based on the cnum returned. */
  39.             break;
  40.     }
  41.  
  42.     return;
  43. }
  44.  
  45.  
  46. The above code isn't all that ugly.  If you have just two document types,
  47. then this may be what you want to do.  However, it isn't too hard to see that
  48. if you have many document types, then the above case statements are just going
  49. to grow and grow.  Also, if each document type has a lot of buttons or content
  50. processing, then each individual case statement will be complex, as well.  This
  51. isn't very object-oriented at all.
  52.  
  53. The new and better way to handle this problem is with the three PartMaker documents
  54. that are now included with AppsToGo.  They are:
  55.  
  56. 1) AWNewDialog
  57. 2) AWNewDoc
  58. 3) AWNewPalette
  59.  
  60. The above PartMaker documents, along with a copy of PartMaker 2.2, can be found in
  61. the folder AppWannabeNewDocs.
  62.  
  63. Let's say that for a while you assumed that your application would only have one
  64. palette.  You just dropped your code into the stub functions in the file
  65. WindowPalette.c in your project, and everything worked just fine.  Now you realize
  66. that your project needs another palette.  You don't want to start adding case
  67. statements into code that already works, so therefore you want the code for the
  68. new palette in a file other than WindowPalette.c.  No problem.  Just double-click
  69. AWNewPalette, type in a name, and click "Create Palette".  PartMaker will create a
  70. folder that contains two files.
  71.  
  72. One of the files will be a source file that you will want to add to your project.
  73. The other file will contain step-by-step instructions as to what else you will need
  74. to do to instantiate your new palette.  (The code changes that it lists will be to
  75. the file File.c, for example.)
  76.  
  77. Now when this palette is instianted, the functions in the new source file will be
  78. called, instead of the funcitons in the file WindowPalette.c.  Now that's reasonably
  79. object-oriented, and we're still in C.
  80.  
  81.  
  82.  
  83. Another issue is that different documents may be related.  If you close
  84. a document, you may also need to close other documents that were created in
  85. relation to that document.  You will have to handle these issues yourself, although
  86. it isn't hard.  You are messaged as to when a window/document is being closed.  If
  87. that window has alternate views that should be closed at the same time, just search
  88. the window list for documents of that type, and close them right then.
  89.  
  90. Yes, it is okay to close them recursively.  The AppsToGo editor uses this very
  91. technique.  Just remember that when you close a window, the window list shrinks
  92. in length, so walking the window list as it shrinks can get a bit tricky.  What
  93. I do is if I close a window, I just start over at the beginning of the window list.
  94.  
  95.  
  96.  
  97. There are interator functions in the framework that conveniently allow you to
  98. find the next document of a certain type.  These iterators walk the window list
  99. looking for the next window that has a document of a certain type.  This means
  100. that you can use these iterators only for documents that have a window.  Just use
  101. this iterator to search for the next window that needs to get closed in relation
  102. to the window being closed, searching from the beginning of the list.  The overhead
  103. of looking through the entire list is absolutely nothing as compared to the actual
  104. work involved in closing a window.
  105.  
  106.  
  107.  
  108. If you are a heavy user of the hierarchical document architecture, you may end
  109. up with two different root object definitions for two different document types.
  110. It is convenient to store some non-undoable state data in the root object, but
  111. if two different documents have different state data, having only one root
  112. object type can get confusing.  Due to this, you may find it useful to sub-type
  113. the root object in these instances.
  114.  
  115. The standard root object definitions looks like this:
  116.  
  117. long    TRootObj(TreeObjHndl hndl, short message, long data);
  118. typedef struct {
  119.     TreeObjHndl    undo;        /* This structure may be added to, but */
  120.     FileRecHndl    frHndl;        /* these two first fields must remain. */
  121. } RootObj;
  122.  
  123. You may wish to extend this to be something like the following:
  124.  
  125. long    TRootObj(TreeObjHndl hndl, short message, long data);
  126. typedef struct {
  127.     TreeObjHndl    undo;        /* This structure may be added to, but */
  128.     FileRecHndl    frHndl;        /* these two first fields must remain. */
  129.     short        subtype;    /* Identifier for variant of root object. */
  130.     union {
  131.         Root1    r1;            /* Union in the various root definitions here. */
  132.         Root2    r2;
  133.     } st;
  134. } RootObj;
  135.  
  136.  
  137. The code for the root object that is called by the framework would
  138. look something like:
  139.  
  140. long    TRootObj(TreeObjHndl hndl, short message, long data)
  141. {
  142.     TreeObjProcPtr    proc;
  143.  
  144.     if (proc = gRootMethods[mDerefRoot(hndl)->subtype])
  145.         return((*proc)(hndl, message, data);
  146.  
  147.     return(0);
  148. }
  149.  
  150. This code is dispatched to for a root object of whatever subtype.  It in
  151. turn then dispatches to the code for the subtype of the root object.  A
  152. table of procedures called gRootMethods is assumed here.  It would be
  153. constructed similarly to the gTreeObjMethods table found in the file “File.c”.
  154.  
  155.  
  156. The rest is simply a matter of writing code.  You will probably want to
  157. reference the various samples that use the framework to see how certain
  158. issues were addressed.
  159.  
  160.  
  161.